/*
     Copyright 2007 Joseph M. Ferner

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

using System;
using System.IO;
using System.Text;
using NMock2;
using NUnit.Framework;

namespace OpenServers.Net.Common.FileSystem.Disk {
    [TestFixture]
    public class DiskFileTest : BaseNMockTest {
        private DiskFile _diskFile;
        private string _tempPath;
        private string _filePath;

        [SetUp]
        public override void SetUp() {
            base.SetUp();

            _tempPath = Path.GetTempPath() + "\\DiskFileTest";
            Directory.CreateDirectory(_tempPath);
            _filePath = _tempPath + "/a.txt";
            File.WriteAllText(_filePath, "Hello World");
            _diskFile = new DiskFile(null, _filePath);
        }

        [TearDown]
        public override void TearDown() {
            Directory.Delete(_tempPath, true);

            base.TearDown();
        }

        [Test]
        public void TestFileInfoConstructor() {
            IFile f = new DiskFile(null, new FileInfo(_tempPath + "/b.txt"));
            Assert.IsNotNull(f);
        }

        [Test]
        public void TestOpenInputStream() {
            Stream input = _diskFile.OpenInputStream();
            try {
                StreamReader reader = new StreamReader(input);
                string allData = reader.ReadToEnd();
                Assert.AreEqual("Hello World", allData);
            } finally {
                input.Close();
            }
        }

        [Test]
        public void TestOpenOutputStream() {
            Stream output = _diskFile.OpenOutputStream();
            try {
                StreamWriter writer = new StreamWriter(output);
                writer.Write("Test Data");
                writer.Close();
            } finally {
                output.Close();
            }

            string readData = File.ReadAllText(_filePath);
            Assert.AreEqual("Test Data", readData);
            Assert.IsNotNull(_diskFile.LastModified);
            Assert.AreEqual(false, _diskFile.ReadOnly);
        }

        [Test]
        public void TestSize() {
            Assert.AreEqual(11, _diskFile.Size);
        }

        [Test]
        public void TestMoveToFile() {
            IFile newFile = Mocks.NewMock<IFile>();
            MemoryStream stream = new MemoryStream();
            Expect.Once.On(newFile).Method("OpenOutputStream").Will(Return.Value(stream));

            _diskFile.MoveTo(newFile);

            string result = ASCIIEncoding.ASCII.GetString(stream.ToArray());
            Assert.AreEqual("Hello World", result);
            Assert.IsFalse(File.Exists(_filePath));
        }

        [Test]
        public void TestMoveToDirectory() {
            IDirectory newDir = Mocks.NewMock<IDirectory>();
            IFile newFile = Mocks.NewMock<IFile>();
            MemoryStream stream = new MemoryStream();
            Expect.Once.On(newDir).Method("CreateFile").Will(Return.Value(newFile));
            Expect.Once.On(newFile).Method("OpenOutputStream").Will(Return.Value(stream));

            _diskFile.MoveTo(newDir);

            string result = ASCIIEncoding.ASCII.GetString(stream.ToArray());
            Assert.AreEqual("Hello World", result);
            Assert.IsFalse(File.Exists(_filePath));
        }

        [Test]
        public void TestMoveToBadType() {
            try {
                IFileSystemObject fso = Mocks.NewMock<IFileSystemObject>();
                _diskFile.MoveTo(fso);
                Assert.Fail("should have thrown an exception");
            } catch (Exception) {
                // ok
            }
        }
    }
}
